package com.itany.corejava.code08_常用类.string;

/**
 * @author 石小俊
 * @date 2023年04月26日 15:57
 */
public class Test11_常量池 {

    public static void main(String[] args) {
        // 通过构造方法创建的字符串,都是存储在堆中
        // 在堆中开辟一块空间,其值为admin
        String s = new String("admin");
        // 在堆中重新开辟了一块空间,其值为alice
        // 由于之前的admin的空间没有被任何对象所引用,其引用计数为0
        // 因此,等待gc销毁
        s = new String("alice");

        // 此时又会在堆中开辟了一块新的空间,其值为admin
        String s2 = new String("admin");

        // 通过双引号创建的字符串都是存储在常量池中
        // 在常量池中开辟了一块新的空间,其值为admin
        String s3 = "admin";
        // 在常量池中开辟了一块新的空间,其值为alice
        s3 = "alice";
        // 此时由于常量池中已经存在admin的空间
        // 因此,s4没有开辟新的空间,而是直接指向原有的admin空间
        String s4 = "admin";

        String s5 = new String("admin");
        // s2与s5所在的空间地址不同,则为false
        System.out.println(s2 == s5);

        String s6 = "admin";
        // s4与s6都在常量池中,处于同一块空间,因此值为true
        System.out.println(s4 == s6);

        String s7 = "a";
        String s8 = "aa";
        String s9 = "aaa";
        String s10 = s7 + s8;
        // s10不是字符常量,其值是运行时确定的,而不是通过双引号给的
        // 当运行前不确定的值是不会被存放到常量池中的
        // 因此,此时的s10存储在堆中
        System.out.println(s9 == s10); // false

        // 由于此时运行前已经能够确定所有的值,因此直接存储到常量池中
        String s11 = "a" + "aa";
        System.out.println(s9 == s11); // true

        String s12 = "a" + s8;
        System.out.println(s9 == s12); // false

        // 当前方法中共有11个对象
        // 其中堆中有6个,常量池中有5个

    }

}
